﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace puerto_serie
{
    public class ControladorJuego:Observable  
    {
        private Tablero TableroJugador_;
        private Tablero TableroMaquina_;
        private JugadorCpu Cpu_;
        private Observer SujetoObservador;
        private int State;
        private ConvertidorDeDatos convertidor;
        private int PosicionXRecibida_, PosicionYRecibida_,CantidadDeDatosRecibidos_,Direccion_;
        public ControladorJuego ()
        {
            convertidor = new ConvertidorDeDatos();
            TableroJugador_ = new Tablero(1);
            TableroMaquina_ = new Tablero(2);
            Cpu_ = new JugadorCpu(TableroMaquina_);
            State = 0;
            CantidadDeDatosRecibidos_ = 0;
        }
        /// <summary>
        /// Codigo que recive mensaje de interfaz, lo cuales son los 
        /// que recibio del puerto serie
        /// </summary>
        /// <param name="datoRecibido"></param>
        public void ReceiveMessage(int datoRecibido)
        {
            if (datoRecibido == 15)
            {
                Console.WriteLine("Gano Maquina");
                State = 6;
            }
            else if (datoRecibido == 240)
            {
                Console.WriteLine("Gano Jugador");
                State = 6;
            }
            else if (State == 4)
            {
                if (CantidadDeDatosRecibidos_ == 0)
                {
                    Console.WriteLine("Se recibio x");
                    PosicionXRecibida_ = datoRecibido;
                    CantidadDeDatosRecibidos_++;
                }
                else
                {
                    Console.WriteLine("Se recibio y");
                    PosicionYRecibida_ = datoRecibido;
                    CantidadDeDatosRecibidos_ = 0;
                    ControlJuego();
                }
            }
            else
            {
                CantidadDeDatosRecibidos_ = 0;
            }
            
        }
        /// <summary>
        /// Metodo para enlazar un sujeto observado con su observador
        /// </summary>
        /// <param name="SujetoObservador"></param>
        public void Attach(Observer SujetoObservador)
        {
            this.SujetoObservador = SujetoObservador;
        }
        /// <summary>
        /// Codigo que notifica a un observador que su sujeto
        /// observado se ha modificado, de modo que se debe actualizar
        /// </summary>
        /// <param name="datoAEnviar"></param>
        public void Notify(byte datoAEnviar)
        {
            Console.WriteLine(datoAEnviar);
            SujetoObservador.Update(datoAEnviar);
        }
        /// <summary>
        /// Codigo para establecer parametros con los cuales se va a ingresar 
        /// un barco a la matriz del jugador
        /// </summary>
        /// <param name="datox"></param>
        /// <param name="datoy"></param>
        /// <param name="direccion"></param>
        public void SetParameters(int datox,int datoy, int direccion)
        {
            PosicionXRecibida_ = datox;
            PosicionYRecibida_ = datoy;
            Direccion_ = direccion;
        }
        /// <summary>
        /// Codigo para enviar matrices y sus ubicaciones a la FPGA
        /// </summary>
        /// <param name="tableroAnalizado"></param>
        private void MandarPosicionesConBarcos(Tablero tableroAnalizado)
        {
            byte bAEnviar;
            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    if (tableroAnalizado.obtenerValorDePosicion(j, i) == 1)
                    {
                        convertidor.convertirColumnaAbitArray(j);
                        convertidor.convertirFilaAbitArray(i);
                        convertidor.convertirResultadoAbitArray(1);
                        bAEnviar = convertidor.convertirBytes();
                        this.Notify(bAEnviar);
                        Thread.Sleep(500);
                    }
                }
            }
        }
        public void adherirFormATableros(FormEscogerBarco interfazDeBarcos)
        {
            TableroJugador_.setFormDeBarco(interfazDeBarcos);
            TableroMaquina_.setFormDeBarco(interfazDeBarcos);
            ControlJuego();
        }
        /// <summary>
        /// Codigo de control del juego, el cual se encarga de manejar diferentes 
        /// estados, donde los diferentes estados indican un comportamiento de algun
        /// momento del juego
        /// </summary>
        public void ControlJuego()
        {
            switch (State)
            {
                case 0:
                    Cpu_.IniciarPosicionesCpu();
                    State = 1;
                    TableroMaquina_.imprimirTablero();
                    Console.WriteLine("");
                    break;
                case 1:
                    TableroJugador_.establishShip(Direccion_, PosicionXRecibida_, PosicionYRecibida_);
                    TableroJugador_.imprimirTablero();
                    Console.WriteLine("");
                    if (TableroJugador_.obtenerCantidadDeBarcosInsertados()==5)
                    {
                        State = 2;
                        ControlJuego();
                    }
                    else
                    {
                        State = 1;
                    }
                    break;
                case 2:
                    State = 3;
                    MandarPosicionesConBarcos(TableroJugador_);
                    ControlJuego();
                    //Madar Posiciones Jugador
                    break;
                case 3:
                    State = 4;
                    MandarPosicionesConBarcos(TableroMaquina_);
                    //Mandar Posiciones Compu
                    break;
                case 4:
                    TableroMaquina_.shoot(PosicionXRecibida_, PosicionYRecibida_);            
                    State = 5;
                    TableroMaquina_.imprimirTablero();
                    MessageBox.Show("Se terminaron de enviar los datos");
                    Console.WriteLine("");
                    ControlJuego();
                    break;
                case 5:
                    Thread.Sleep(25);
                    int Resultado=Cpu_.RealizarJugada(TableroJugador_);
                    int x=Cpu_.obtenerUltimaPosicionXDisparada();
                    int y = Cpu_.obtenerUltimaPosicionYDisparada();
                    convertidor.convertirColumnaAbitArray(x);
                    convertidor.convertirFilaAbitArray(y);
                    convertidor.convertirResultadoAbitArray(Resultado);
                    byte bAEnviar= convertidor.convertirBytes();
                    this.Notify(bAEnviar);
                    TableroJugador_.imprimirTablero();
                    Console.WriteLine("");
                    State = 4;
                    break;
                case 6:
                    Console.WriteLine("Se acabo el juego");
                    break;
                default:
                    Console.WriteLine("Default case");
                    break;
            }
        }
    }
}
